#include"../Source/server.hpp"

//test bugs:
//1. 读事件关心只有一次？       写完后调用的DisableWrite写成了{_events &= ~  EPOLLIN  ; Update();}
//2. 客户端断了服务器也断开？   和1有关，因为1并没有真正去除写关心，导致服务器端向一个已关闭的连接（文件描述符）的继续发送数据
//3. 不停执行任意事件的回调？   和1有关，因为读回调ReadHandle只调用了一次，故也就没有没有预期的recv的阻塞效果

void CloseHandle(Channel* channel)
{   
    DBG_LOG("CloseHandle");
    channel->Remove();
    delete channel;
}

void ReadHandle(Channel* channel, EventLoop* loop)
{
    char buffer[1280] = {0};
    int n = recv(channel->Getfd(), buffer, sizeof(buffer),0);
    if(n <= 0)
    {
        CloseHandle(channel);         //?:如果这里不手动调，靠HandEvent调用的话，读事件就绪判断会一直为真，会一直执行任意事件回调！
        return;
    }

    loop->TimerRefresh(1234);       //刷新活跃度
    DBG_LOG("read buffer: %s", buffer);
    //channel->EnableWrite();
}

void WriteHandle(Channel* channel)
{
    char msg[] = "hello, i am server...";
    send(channel->Getfd(), msg, sizeof(msg), 0);

    channel->DisableWrite();    //写不能设置为常关心 写完后直接关闭对写事件的监控
}

void AnyHandle(Channel* channel)
{
    //DBG_LOG("fd is %d", channel->Getfd());
    cout << "Anything!" << endl;
    //sleep(1);     //?: 不加就会刷屏
}

void TimeOutTask()
{
    cout << "TimeOut !!!" << endl;
    exit(1);
}

void OnCreate(const PtrConnection& pcon)
{
    DBG_LOG("OnCreate");
}

void OnMessage(const PtrConnection& pcon, Buffer* buf)
{
    DBG_LOG("OnMessage");
    char buffer[2048] = {0};
    buf->Read(buffer, buf->GetReadableSize());

    cout << "server recv: " << buffer << endl;
}

void OnClosed(const PtrConnection& pcon)
{
    DBG_LOG("OnClosed");
}

void OnAnyEvent(const PtrConnection& pcon)
{
    DBG_LOG("OnAnyEvent");
}


std::unordered_map<uint64_t, PtrConnection> connects;
void DestoryConnection()
{

}

void AcceptorForEventLoop(Channel* lisch, EventLoop* loop)
{
    DBG_LOG("Acceptor");
    int newfd = accept(lisch->Getfd(), nullptr, nullptr);
    if(newfd < 0)  
    {
        return;
    }

    Channel* ch = new Channel(newfd, loop);

    loop->TimerAdd(1234,5,std::bind(TimeOutTask));  //添加定时任务

    ch->SetReadCallback(std::bind(ReadHandle, ch, loop));
    ch->SetWriteCallback(std::bind(WriteHandle, ch));
    ch->SetAnyCallback(std::bind(AnyHandle, ch));
    ch->SetErrorCallback(std::bind(CloseHandle, ch));
    ch->SetCloseCallback(std::bind(CloseHandle, ch));
    ch->EnableRead();
}

//LoopThread mainloop;
EventLoop baseloop;

void AcceptorForConnection(Channel* lisch, EventLoop* loop)
{
    int newfd = accept(lisch->Getfd(), nullptr, nullptr);
    if(newfd < 0)  
    {
        return;
    }

    PtrConnection pc(new Connection(1,loop,newfd));
    connects[1] = pc;
    // pc->SetConnectedCallback(OnCreate);
    // pc->SetMessageCallback(OnMessage);
    // pc->SetClosedCallback(OnClosed);
    // pc->SetAnyEventCallback(OnAnyEvent);

    pc->SetConnectedCallback(std::bind(OnCreate, std::placeholders::_1));
    pc->SetMessageCallback(std::bind(OnMessage, std::placeholders::_1, std::placeholders::_2));
    pc->SetClosedCallback(std::bind(OnClosed, std::placeholders::_1));
    pc->SetAnyEventCallback(std::bind(OnAnyEvent, std::placeholders::_1));

    pc->Established();
    pc->EnableInactiveRelease(3);
}

// void AcceptorTest(int newfd)
// {
//     PtrConnection pc(new Connection(1,&loop,newfd));
//     connects[1] = pc;

//     pc->SetConnectedCallback(std::bind(OnCreate, std::placeholders::_1));
//     pc->SetMessageCallback(std::bind(OnMessage, std::placeholders::_1, std::placeholders::_2));
//     pc->SetClosedCallback(std::bind(OnClosed, std::placeholders::_1));
//     pc->SetAnyEventCallback(std::bind(OnAnyEvent, std::placeholders::_1));

//     pc->Established();
//     pc->EnableInactiveRelease(3);
// }

//测试时从线程也得是全局的，因为即使它会去while(1),但其生命周期还是在主线程的花括号中;  或者用join

vector<LoopThread> slavethreads(2);
int next_loop_i = 0;
int conn_id = 1;
//bug: 第二个新连接到来，管理第一个连接的某个channel销毁？
//fix: 之前测试图方便直接手动设置了一个conn_id,导致加入哈希表时把第一个连接覆盖了，第一个连接也就销毁了！
void LoopThreadTest(int newfd)
{
    next_loop_i = (next_loop_i + 1) % 2; 
    
    PtrConnection pc(new Connection(conn_id,slavethreads[next_loop_i].GetEventLoop(),newfd));
    connects[conn_id] = pc;

    pc->SetConnectedCallback(std::bind(OnCreate, std::placeholders::_1));
    pc->SetMessageCallback(std::bind(OnMessage, std::placeholders::_1, std::placeholders::_2));
    pc->SetClosedCallback(std::bind(OnClosed, std::placeholders::_1));
    pc->SetAnyEventCallback(std::bind(OnAnyEvent, std::placeholders::_1));

    pc->Established();
    pc->EnableInactiveRelease(3);    
    conn_id++;
}

//fix bug: 要在同一个poller底下进行事件监控！！！
int main()
{
    // Socket sock;
    // EventLoop loop;
    // sock.ServerConnect();
    // Channel lisch(sock.Getfd(), &loop);

    // DBG_LOG("listensock is: %d", sock.Getfd());

    // lisch.SetReadCallback(std::bind(AcceptorForConnection, &lisch, &loop));
    // lisch.EnableRead();
    //fix bug: epoll_wait等的是已经就绪的事件，对于监听套接字，唯一可以就绪的读事件就是accept！！
    //而这里在EnableRead之前就已经accept了！！！导致读事件在关心后一直无法就绪！！！故导致epoll_wait一直阻塞！！！

    //Acceptor acc(mainloop.GetEventLoop());
    Acceptor acc(&baseloop);
    
    acc.Listen();
    acc.SetAcceptCallback(LoopThreadTest);

    // LoopThreadPool pool(&baseloop);
    // pool.SetThreadCount(2);
    // pool.CreateSlaveThread();


    baseloop.Start();
    

    return 0;
}